package com.hust.yuqian.dcts;

/**
 * Created by mmutuyu on 14-1-10.
 */

/*
 ****************************************************************************
 *
 * Inverse Discrete Cosine Transform (IDCT) 离散余弦逆变换, 可看作一个谐波合成器
 * From: http://www.cyut.edu.tw/~yltang/utility.html
 ****************************************************************************
 */

public class IDct {

    /**
     *
     * @param nrows 原始图像行数
     * @param ncols 原始图像列数
     * @param dct 原始图片DCT转换后的矩阵
     * @return 原始图像的'b'值数组
     */
    public static int[][] operation(int nrows, int ncols, double[][] dct){
        final int N = 8;  // Block size
        int m, n, x, y, u, v, b[][];
        double sum, au, av, tmp;
        double  n1=Math.sqrt(1.0/N), n2=Math.sqrt(2.0/N);

        if (nrows%N!=0 || ncols%N!=0) {
            System.out.println("Nrows and ncols should be multiples of 8");
            System.exit(0);
        }

        b = new int[nrows][ncols];

        // For each NxN block[m,n]
        for (m=0; m<nrows; m+=N) {
            for (n=0; n<ncols; n+=N) {

                // For each pixel[x,y] in block[m,n]
                for (x=m; x<m+N; x++) {
                    for (y=n; y<n+N; y++) {

                        // Sum up all pixels in the block
                        for (u=m, sum=0; u<m+N; u++) {
                            au = (u==m)? n1: n2;
                            for (v=n; v<n+N; v++) {
                                av = (v==n)? n1: n2;
                                sum += au * av *
                                        dct[u][v] * Math.cos((2*(x-m)+1)*(u-m)*Math.PI/(2*N)) *
                                        Math.cos((2*(y-n)+1)*(v-n)*Math.PI/(2*N));
                            }  // for v
                        }  // for u

                        // Add 128 and copy to output image
                        tmp = sum + 128.5;  // Add 128
                        if (tmp > 255) b[x][y] = 255;
                        else if (tmp < 0) b[x][y] = 0;
                        else b[x][y] = (int)tmp;

                    }  // for x
                }  // for y

            }  // for n
        }  // for m

        return b;
    }
}
